import os
import subprocess
import sys
from typing import List, Optional, Dict
import tkinter as tk
from tkinter import ttk, filedialog, messagebox


class TSMergerGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("TS视频合并工具 - 自动遍历E盘视频录制文件夹")
        self.root.geometry("1100x750")
        self.root.resizable(True, True)

        # 全局变量
        self.default_root_path = r"E:\视频录制"  # 固定根目录
        self.found_ts_folders: Dict[str, List[str]] = {}  # {TS文件夹路径: [排序后的TS文件列表]}
        self.selected_ts_folder: Optional[str] = None  # 当前选择的TS文件夹
        self.save_mode = tk.StringVar(value="same_dir")  # same_dir（同级）/ custom_dir（自定义）
        self.custom_save_path: Optional[str] = self.default_root_path  # 自定义保存路径

        # 初始化默认路径（创建E:\视频录制）
        self._init_default_paths()

        # 构建界面
        self._setup_ui()

        # 启动后自动扫描TS文件夹
        self.scan_ts_folders(auto_scan=True)

    def _init_default_paths(self):
        """初始化默认路径（创建E:\视频录制）"""
        try:
            if not os.path.exists(self.default_root_path):
                os.makedirs(self.default_root_path)
                messagebox.showinfo(
                    "路径创建成功",
                    f"已自动创建默认根目录：{self.default_root_path}\n"
                    "请将TS文件所在文件夹放入该目录下"
                )
        except Exception as e:
            messagebox.showerror(
                "路径创建失败",
                f"无法创建默认根目录「E:\\视频录制」\n"
                f"错误原因：{str(e)}\n"
                "程序将无法自动扫描，请手动选择根目录"
            )
            self.default_root_path = ""

    def _setup_ui(self):
        """构建界面（修复ttk.Radiobutton不支持font参数的问题）"""
        # 1. 顶部功能区（新增搜索目录和输出路径按钮）
        func_frame = ttk.Frame(self.root, padding="10", relief=tk.RAISED)
        func_frame.pack(fill=tk.X, expand=False, anchor=tk.N)

        # 搜索目录相关
        ttk.Label(func_frame, text="搜索根目录:", font=("Arial", 10, "bold")).grid(row=0, column=0, padx=5, pady=5,
                                                                              sticky=tk.E)
        self.root_folder_label = ttk.Label(
            func_frame,
            text=self.default_root_path if self.default_root_path else "未找到E:\\视频录制",
            width=45,
            wraplength=350,
            foreground="green" if self.default_root_path else "red"
        )
        self.root_folder_label.grid(row=0, column=1, padx=5, pady=5, sticky=tk.W)

        self.open_root_btn = ttk.Button(
            func_frame,
            text="打开搜索目录",
            command=lambda: self._open_folder(self.default_root_path if self.default_root_path else None),
            style="Accent.TButton"
        )
        self.open_root_btn.grid(row=0, column=2, padx=5, pady=5, sticky=tk.W)

        self.rescan_btn = ttk.Button(
            func_frame,
            text="重新扫描所有文件夹",
            command=self.scan_ts_folders,
            style="Accent.TButton"
        )
        self.rescan_btn.grid(row=0, column=3, padx=5, pady=5, sticky=tk.W)

        # 2. 保存模式与输出路径区
        save_frame = ttk.Frame(self.root, padding="10")
        save_frame.pack(fill=tk.X, expand=False, anchor=tk.N)

        # 保存模式选择（移除ttk.Radiobutton的font参数）
        ttk.Label(save_frame, text="保存模式:", font=("Arial", 10, "bold")).grid(row=0, column=0, padx=5, pady=5,
                                                                             sticky=tk.E)
        ttk.Radiobutton(
            save_frame,
            text="保存到TS文件夹同级目录",
            variable=self.save_mode,
            value="same_dir",
            command=self.update_save_mode_ui
        ).grid(row=0, column=1, padx=5, pady=5, sticky=tk.W)
        ttk.Radiobutton(
            save_frame,
            text="统一保存到自定义目录",
            variable=self.save_mode,
            value="custom_dir",
            command=self.update_save_mode_ui
        ).grid(row=0, column=2, padx=5, pady=5, sticky=tk.W)

        self.select_custom_save_btn = ttk.Button(
            save_frame,
            text="选择自定义保存路径",
            command=self.select_custom_save_path,
            state=tk.DISABLED,
            style="Accent.TButton"
        )
        self.select_custom_save_btn.grid(row=0, column=3, padx=5, pady=5, sticky=tk.W)

        # 输出路径显示与查看按钮
        ttk.Label(save_frame, text="当前输出路径:", font=("Arial", 10, "bold")).grid(row=1, column=0, padx=5, pady=5,
                                                                               sticky=tk.E)
        self.output_path_label = ttk.Label(
            save_frame,
            text="请选择TS文件夹查看输出路径",
            width=50,
            wraplength=400,
            foreground="#333",
            font=("Arial", 10)
        )
        self.output_path_label.grid(row=1, column=1, padx=5, pady=5, sticky=tk.W, columnspan=2)

        self.open_output_btn = ttk.Button(
            save_frame,
            text="查看输出路径",
            command=self.open_current_output_path,
            state=tk.DISABLED,
            style="Accent.TButton"
        )
        self.open_output_btn.grid(row=1, column=3, padx=5, pady=5, sticky=tk.W)

        # 3. 文件夹选择与合并按钮区（突出显示开始合并按钮）
        merge_frame = ttk.Frame(self.root, padding="10", relief=tk.GROOVE)
        merge_frame.pack(fill=tk.X, expand=False, anchor=tk.N)

        ttk.Label(merge_frame, text="选择要合并的TS文件夹:", font=("Arial", 10, "bold")).grid(row=0, column=0, padx=5, pady=5,
                                                                                     sticky=tk.E)
        self.ts_folder_combobox = ttk.Combobox(merge_frame, width=60, state="readonly")  # 移除ttk.Combobox的font参数
        self.ts_folder_combobox.grid(row=0, column=1, padx=5, pady=5, sticky=tk.W + tk.E, columnspan=2)
        self.ts_folder_combobox.bind("<<ComboboxSelected>>", self.on_ts_folder_selected)

        # 单个合并按钮（突出显示）
        self.merge_single_btn = ttk.Button(
            merge_frame,
            text="开始合并当前选择文件夹",
            command=self.start_merge_single,
            state=tk.DISABLED,
            style="Success.TButton"
        )
        self.merge_single_btn.grid(row=0, column=3, padx=5, pady=5, sticky=tk.W)

        # 批量合并按钮
        self.merge_all_btn = ttk.Button(
            merge_frame,
            text="批量合并所有TS文件夹",
            command=self.start_merge_all,
            state=tk.DISABLED,
            style="Warning.TButton"
        )
        self.merge_all_btn.grid(row=0, column=4, padx=5, pady=5, sticky=tk.E)

        # 4. 中间文件列表区
        list_frame = ttk.Frame(self.root, padding="10")
        list_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 10))

        title_frame = ttk.Frame(list_frame)
        title_frame.pack(fill=tk.X, expand=False, anchor=tk.W)
        ttk.Label(title_frame, text="当前文件夹下的TS文件（按数字顺序）:", font=("Arial", 11, "bold")).pack(side=tk.LEFT)
        self.file_count_label = ttk.Label(title_frame, text="(0个文件)", font=("Arial", 10))
        self.file_count_label.pack(side=tk.LEFT, padx=10)
        self.folder_path_label = ttk.Label(title_frame, text="", font=("Arial", 9), foreground="#666")
        self.folder_path_label.pack(side=tk.LEFT, padx=10)

        scrollbar = ttk.Scrollbar(list_frame)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        self.file_listbox = tk.Listbox(
            list_frame,
            yscrollcommand=scrollbar.set,
            font=("Arial", 10),
            selectbackground="#e0e0e0",
            bg="white",
            height=15
        )
        self.file_listbox.pack(fill=tk.BOTH, expand=True, padx=(0, 5))
        scrollbar.config(command=self.file_listbox.yview)

        # 5. 底部状态区
        status_frame = ttk.Frame(self.root, padding="10")
        status_frame.pack(fill=tk.X, expand=False, anchor=tk.S)

        self.status_label = ttk.Label(
            status_frame,
            text="正在初始化并扫描TS文件夹...",
            font=("Arial", 10)
        )
        self.status_label.pack(anchor=tk.W, pady=5)

        self.progress_var = tk.DoubleVar()
        self.progress_bar = ttk.Progressbar(
            status_frame,
            variable=self.progress_var,
            maximum=100,
            mode="determinate"
        )
        self.progress_bar.pack(fill=tk.X, padx=5, pady=5, expand=True)
        self.progress_bar.pack_forget()

        # 样式配置（突出关键按钮）
        self.root.style = ttk.Style()
        self.root.style.configure("Accent.TButton", font=("Arial", 10, "bold"), foreground="white",
                                  background="#2196F3")
        self.root.style.configure("Success.TButton", font=("Arial", 11, "bold"), foreground="white",
                                  background="#4CAF50", padding=10)
        self.root.style.configure("Warning.TButton", font=("Arial", 10, "bold"), foreground="white",
                                  background="#FF5722")

    def _get_sorted_ts_files(self, folder_path: str) -> List[str]:
        """查找单个文件夹下的TS文件并按数字排序"""
        ts_files = []
        for filename in os.listdir(folder_path):
            file_path = os.path.join(folder_path, filename)
            if os.path.isfile(file_path) and filename.lower().endswith(".ts"):
                try:
                    num_part = ''.join(filter(str.isdigit, filename))
                    if not num_part:
                        continue
                    file_num = int(num_part)
                    ts_files.append((file_num, os.path.abspath(file_path)))
                except Exception:
                    continue

        ts_files.sort(key=lambda x: x[0])
        return [path for _, path in ts_files]

    def scan_ts_folders(self, auto_scan: bool = False):
        """扫描E:\视频录制及其子文件夹，查找包含TS文件的文件夹"""
        if not self.default_root_path or not os.path.exists(self.default_root_path):
            if not auto_scan:
                self.default_root_path = filedialog.askdirectory(title="选择TS文件根目录（自动递归查找）")
                if not self.default_root_path:
                    messagebox.showwarning("警告", "未选择根目录，扫描取消")
                    return
            else:
                messagebox.showwarning("警告", "未找到根目录「E:\\视频录制」，无法自动扫描")
                self.status_label.config(text="未找到根目录，无法扫描")
                return

        self.root_folder_label.config(text=self.default_root_path, foreground="green")
        self.status_label.config(text=f"正在扫描：{self.default_root_path}（包含所有子文件夹）...")
        self.root.update_idletasks()

        # 清空之前的结果
        self.found_ts_folders.clear()
        self.ts_folder_combobox["values"] = []
        self.file_listbox.delete(0, tk.END)
        self.file_count_label.config(text="(0个文件)")
        self.folder_path_label.config(text="")
        self.output_path_label.config(text="请选择TS文件夹查看输出路径")
        self.open_output_btn.config(state=tk.DISABLED)

        try:
            total_folders = 0
            for root, dirs, files in os.walk(self.default_root_path):
                total_folders += 1
                ts_files = self._get_sorted_ts_files(root)
                if ts_files:
                    self.found_ts_folders[root] = ts_files

            if not self.found_ts_folders:
                messagebox.showwarning("警告", "未在根目录及子文件夹中找到任何TS文件！")
                self.status_label.config(text=f"扫描完成 - 未找到TS文件（共扫描 {total_folders} 个文件夹）")
                self.merge_single_btn.config(state=tk.DISABLED)
                self.merge_all_btn.config(state=tk.DISABLED)
            else:
                # 更新下拉框
                combobox_values = []
                for folder_path in self.found_ts_folders.keys():
                    rel_path = os.path.relpath(folder_path, self.default_root_path)
                    file_count = len(self.found_ts_folders[folder_path])
                    display_text = f"{rel_path}（{file_count}个文件）"
                    combobox_values.append((folder_path, display_text))

                combobox_values.sort(key=lambda x: x[0])
                self.ts_folder_combobox["values"] = [v[1] for v in combobox_values]
                self.ts_folder_combobox.current(0)
                self.selected_ts_folder = combobox_values[0][0]
                self._update_file_list(self.selected_ts_folder)
                self._update_output_path_display()  # 更新输出路径显示

                # 启用按钮
                self.merge_single_btn.config(state=tk.NORMAL)
                self.merge_all_btn.config(state=tk.NORMAL)
                self.open_output_btn.config(state=tk.NORMAL)

                self.status_label.config(
                    text=f"扫描完成 - 找到 {len(self.found_ts_folders)} 个TS文件夹（共扫描 {total_folders} 个文件夹）"
                )

        except Exception as e:
            messagebox.showerror("错误", f"扫描文件夹失败：{str(e)}")
            self.status_label.config(text=f"扫描失败：{str(e)}")

    def _update_file_list(self, folder_path: str):
        """更新当前选择文件夹的TS文件列表"""
        ts_files = self.found_ts_folders.get(folder_path, [])
        self.file_listbox.delete(0, tk.END)

        for i, file_path in enumerate(ts_files, 1):
            filename = os.path.basename(file_path)
            self.file_listbox.insert(tk.END, f"{i:03d}. {filename}")

        self.file_count_label.config(text=f"({len(ts_files)}个文件)")
        self.folder_path_label.config(text=f"源文件夹路径：{folder_path}")

    def _update_output_path_display(self):
        """更新当前选择文件夹的输出路径显示"""
        if not self.selected_ts_folder:
            self.output_path_label.config(text="请选择TS文件夹查看输出路径")
            self.open_output_btn.config(state=tk.DISABLED)
            return

        output_path = self._get_output_path(self.selected_ts_folder)
        display_path = output_path if len(output_path) <= 50 else f"...{output_path[-47:]}"
        self.output_path_label.config(text=f"合并后文件：{display_path}")
        self.open_output_btn.config(state=tk.NORMAL)

    def on_ts_folder_selected(self, event):
        """选择下拉框中的TS文件夹"""
        selected_text = self.ts_folder_combobox.get()
        if not selected_text:
            return

        for folder_path, display_text in zip(self.found_ts_folders.keys(), self.ts_folder_combobox["values"]):
            if display_text == selected_text:
                self.selected_ts_folder = folder_path
                self._update_file_list(folder_path)
                self._update_output_path_display()  # 更新输出路径
                break

    def update_save_mode_ui(self):
        """根据保存模式更新UI状态"""
        # 初始化自定义保存路径标签（如果未创建）
        if not hasattr(self, 'custom_save_label'):
            self.custom_save_label = ttk.Label(
                self.save_frame,
                text=self.custom_save_path,
                width=50,
                wraplength=400,
                font=("Arial", 10)
            )
            self.custom_save_label.grid(row=2, column=1, padx=5, pady=5, sticky=tk.W, columnspan=2)

        if self.save_mode.get() == "custom_dir":
            self.select_custom_save_btn.config(state=tk.NORMAL)
            self.custom_save_label.config(foreground="green")
        else:
            self.select_custom_save_btn.config(state=tk.DISABLED)
            self.custom_save_label.config(foreground="#666")

        # 切换保存模式后更新输出路径显示
        if self.selected_ts_folder:
            self._update_output_path_display()

    def select_custom_save_path(self):
        """选择自定义保存路径"""
        save_folder = filedialog.askdirectory(title="选择统一保存路径")
        if not save_folder:
            return

        self.custom_save_path = save_folder
        # 确保自定义路径标签已创建
        if not hasattr(self, 'custom_save_label'):
            self.custom_save_label = ttk.Label(
                self.save_frame,
                text=self.custom_save_path,
                width=50,
                wraplength=400,
                font=("Arial", 10)
            )
            self.custom_save_label.grid(row=2, column=1, padx=5, pady=5, sticky=tk.W, columnspan=2)
        else:
            self.custom_save_label.config(text=self.custom_save_path)

        # 更新输出路径显示
        if self.selected_ts_folder:
            self._update_output_path_display()

        self.status_label.config(text=f"自定义保存路径已更新：{save_folder}")

    def _get_output_path(self, folder_path: str) -> str:
        """根据保存模式获取输出路径（文件名=文件夹名+.mp4）"""
        folder_name = os.path.basename(folder_path)
        output_filename = f"{folder_name}.mp4"

        if self.save_mode.get() == "same_dir":
            output_dir = os.path.dirname(folder_path)
        else:
            output_dir = self.custom_save_path

        output_path = os.path.join(output_dir, output_filename)

        # 处理文件名冲突
        counter = 1
        while os.path.exists(output_path):
            output_filename = f"{folder_name}_{counter}.mp4"
            output_path = os.path.join(output_dir, output_filename)
            counter += 1

        return output_path

    def open_current_output_path(self):
        """打开当前选中文件夹的输出路径"""
        if not self.selected_ts_folder:
            messagebox.showwarning("警告", "请先选择TS文件夹！")
            return

        output_path = self._get_output_path(self.selected_ts_folder)
        output_dir = os.path.dirname(output_path)

        # 确保输出目录存在
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)

        self._open_folder(output_dir)

    def _create_temp_file_list(self, ts_files: List[str], temp_list_path: str) -> None:
        """创建TS文件列表（供ffmpeg使用）"""
        with open(temp_list_path, "w", encoding="utf-8") as f:
            for file in ts_files:
                file_path = file.replace("\\", "/")
                f.write(f"file '{file_path}'\n")

    def start_merge_single(self):
        """开始合并当前选择的单个TS文件夹（突出功能）"""
        if not self.selected_ts_folder or not self.found_ts_folders:
            messagebox.showwarning("警告", "请先选择包含TS文件的文件夹！")
            return

        output_path = self._get_output_path(self.selected_ts_folder)
        ts_files = self.found_ts_folders[self.selected_ts_folder]
        folder_name = os.path.basename(self.selected_ts_folder)

        # 确认合并
        confirm = messagebox.askyesno(
            "确认开始合并",
            f"📹 即将合并文件夹：{folder_name}\n"
            f"📁 包含 {len(ts_files)} 个TS文件\n"
            f"📄 输出文件名：{os.path.basename(output_path)}\n"
            f"💾 保存位置：{os.path.dirname(output_path)}\n"
            f"\n是否开始合并？"
        )
        if not confirm:
            return

        # 准备合并
        self._set_controls_state(tk.DISABLED)
        self.status_label.config(text=f"正在合并：{folder_name}...")
        self.progress_bar.pack(fill=tk.X, padx=5, pady=5, expand=True)
        self.progress_var.set(10)
        self.root.update_idletasks()

        try:
            temp_list_path = os.path.join(os.path.dirname(output_path), "temp_ts_list.txt")
            self._create_temp_file_list(ts_files, temp_list_path)
            self.progress_var.set(30)
            self.root.update_idletasks()

            # 构建ffmpeg命令
            self.status_label.config(text="正在合并视频...（无损合并，速度很快）")
            self.root.update_idletasks()

            command = [
                "ffmpeg",
                "-f", "concat",
                "-safe", "0",
                "-i", temp_list_path,
                "-c", "copy",
                "-bsf:a", "aac_adtstoasc",
                "-y",
                output_path
            ]

            self.progress_var.set(50)
            result = subprocess.run(
                command,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
                text=True,
                encoding="utf-8",
                timeout=None
            )

            if result.returncode == 0:
                self.progress_var.set(100)
                self.status_label.config(text=f"合并成功：{folder_name}")
                messagebox.showinfo(
                    "✅ 合并成功",
                    f"视频合并完成！\n\n"
                    f"源文件夹：{folder_name}\n"
                    f"输出文件：{os.path.basename(output_path)}\n"
                    f"保存位置：{os.path.dirname(output_path)}\n"
                    f"\n是否打开保存文件夹？"
                )
                self._open_folder(os.path.dirname(output_path))
            else:
                raise Exception(f"ffmpeg执行失败：\n{result.stdout[:500]}")

        except Exception as e:
            self.status_label.config(text=f"❌ 合并失败：{folder_name}")
            messagebox.showerror("合并失败", f"合并 {folder_name} 时出错：\n{str(e)}")
            self.progress_var.set(0)
        finally:
            # 清理临时文件
            temp_list_path = os.path.join(os.path.dirname(output_path), "temp_ts_list.txt")
            if os.path.exists(temp_list_path):
                try:
                    os.remove(temp_list_path)
                except:
                    pass

            # 恢复控件状态
            self._set_controls_state(tk.NORMAL)
            self.progress_bar.pack_forget()
            self.root.update_idletasks()

    def start_merge_all(self):
        """批量合并所有TS文件夹"""
        if not self.found_ts_folders:
            messagebox.showwarning("警告", "未找到任何包含TS文件的文件夹！")
            return

        confirm = messagebox.askyesno(
            "确认批量合并",
            f"即将批量合并 {len(self.found_ts_folders)} 个TS文件夹！\n"
            f"输出文件名：每个文件夹名+.mp4\n"
            f"保存模式：{'同级目录' if self.save_mode.get() == 'same_dir' else f'统一目录：{self.custom_save_path}'}\n"
            f"\n是否继续？"
        )
        if not confirm:
            return

        self._set_controls_state(tk.DISABLED)
        self.status_label.config(text=f"开始批量合并 {len(self.found_ts_folders)} 个文件夹...")
        self.progress_bar.pack(fill=tk.X, padx=5, pady=5, expand=True)
        self.progress_var.set(0)
        self.root.update_idletasks()

        success_count = 0
        fail_folders = []
        total_folders = len(self.found_ts_folders)

        try:
            for idx, (folder_path, ts_files) in enumerate(self.found_ts_folders.items(), 1):
                folder_name = os.path.basename(folder_path)
                self.status_label.config(text=f"正在合并 ({idx}/{total_folders})：{folder_name}")
                self.progress_var.set((idx / total_folders) * 90)
                self.root.update_idletasks()

                output_path = self._get_output_path(folder_path)
                temp_list_path = os.path.join(os.path.dirname(output_path), f"temp_ts_list_{idx}.txt")
                self._create_temp_file_list(ts_files, temp_list_path)

                command = [
                    "ffmpeg",
                    "-f", "concat",
                    "-safe", "0",
                    "-i", temp_list_path,
                    "-c", "copy",
                    "-bsf:a", "aac_adtstoasc",
                    "-y",
                    output_path
                ]

                result = subprocess.run(
                    command,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.STDOUT,
                    text=True,
                    encoding="utf-8",
                    timeout=None
                )

                # 清理临时文件
                if os.path.exists(temp_list_path):
                    os.remove(temp_list_path)

                if result.returncode == 0:
                    success_count += 1
                else:
                    fail_folders.append(f"{folder_name}（错误：{result.stdout[:100]}）")

            self.progress_var.set(100)
            self.status_label.config(text="批量合并完成！")

            result_text = f"✅ 批量合并结果汇总：\n"
            result_text += f"总文件夹数：{total_folders}\n"
            result_text += f"成功合并：{success_count}\n"
            result_text += f"合并失败：{len(fail_folders)}\n"

            if fail_folders:
                result_text += f"\n失败文件夹（最多显示5个）：\n" + "\n".join(fail_folders[:5])

            messagebox.showinfo("批量合并完成", result_text)

            if self.save_mode.get() == "custom_dir" and messagebox.askyesno("打开文件夹", "是否立即打开统一保存目录？"):
                self._open_folder(self.custom_save_path)

        except Exception as e:
            self.status_label.config(text="批量合并失败！")
            messagebox.showerror("批量合并失败", f"批量合并过程中出错：\n{str(e)}")
            self.progress_var.set(0)
        finally:
            # 清理所有临时文件
            for idx in range(1, total_folders + 1):
                temp_list_path = os.path.join(self.custom_save_path, f"temp_ts_list_{idx}.txt")
                if os.path.exists(temp_list_path):
                    os.remove(temp_list_path)

            self._set_controls_state(tk.NORMAL)
            self.progress_bar.pack_forget()
            self.root.update_idletasks()

    def _set_controls_state(self, state: str):
        """设置所有控件的启用/禁用状态"""
        self.open_root_btn.config(state=state)
        self.rescan_btn.config(state=state)
        self.ts_folder_combobox.config(state="normal" if state == tk.NORMAL else "disabled")
        self.select_custom_save_btn.config(state=state if self.save_mode.get() == "custom_dir" else tk.DISABLED)
        self.merge_single_btn.config(state=state)
        self.merge_all_btn.config(state=state)
        self.open_output_btn.config(state=state if self.selected_ts_folder else tk.DISABLED)

        # 单选按钮始终启用
        for child in self.save_frame.winfo_children():
            if isinstance(child, ttk.Radiobutton):
                child.config(state=state)

    def _open_folder(self, folder_path: Optional[str]):
        """跨平台打开文件夹"""
        if not folder_path or not os.path.exists(folder_path):
            messagebox.showwarning("警告", "文件夹不存在或未选择！")
            return

        try:
            if sys.platform == "win32":
                os.startfile(folder_path)
            elif sys.platform == "darwin":
                subprocess.run(["open", folder_path])
            else:
                subprocess.run(["xdg-open", folder_path])
        except Exception as e:
            messagebox.showwarning("警告", f"无法打开文件夹：{str(e)}")


def main():
    # 检查ffmpeg是否安装
    try:
        subprocess.run(
            ["ffmpeg", "-version"],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            check=True,
            timeout=5
        )
    except (subprocess.CalledProcessError, FileNotFoundError, TimeoutError):
        messagebox.showerror(
            "错误 - 未找到ffmpeg",
            "❌ 无法找到ffmpeg工具！\n\n请先安装ffmpeg并配置环境变量：\n"
            "• Windows：下载后将bin目录添加到系统环境变量\n"
            "• Mac：打开终端执行 brew install ffmpeg\n"
            "• Linux：打开终端执行 sudo apt install ffmpeg"
        )
        sys.exit(1)

    # 启动GUI
    root = tk.Tk()
    app = TSMergerGUI(root)
    root.mainloop()


if __name__ == "__main__":
    main()